package com.example.rbac.service;

import com.example.rbac.common.RequestHolder;
import com.example.rbac.dao.SysAclMapper;
import com.example.rbac.dao.SysAclModuleMapper;
import com.example.rbac.exception.BusinessException;
import com.example.rbac.exception.ParamException;
import com.example.rbac.model.SysAclModule;
import com.example.rbac.param.AclModuleParam;
import com.example.rbac.util.BeanValidator;
import com.example.rbac.util.IpUtil;
import com.example.rbac.util.LevelUtil;
import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author XieLongzhen
 * @date 2019/1/26 14:30
 */
@Slf4j
@Service
public class SysAclModuleService {

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysLogService sysLogService;

    public boolean save(AclModuleParam param) {
        try {
            BeanValidator.check(param);
            if (checkExist(param.getParentId(), param.getName(), param.getId())) {
                throw new ParamException("同一层级下存在相同名称的权限模块");
            }
            SysAclModule aclModule = SysAclModule.builder().name(param.getName()).parentId(param.getParentId())
                    .seq(param.getSeq()).status(param.getStatus()).remark(param.getRemark())
                    .level(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()))
                    .operator(RequestHolder.getCurrentUser().getUsername())
                    .operateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()))
                    .operateTime(new Date()).build();

            if (sysAclModuleMapper.insertSelective(aclModule) > 0) {
                sysLogService.saveAclModuleLog(null, aclModule);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.info("Add AclModule Failed: {}", e);
            throw new RuntimeException("新增权限模块时出错！系统异常");
        }
    }

    @Transactional
    public boolean update(AclModuleParam param) {
        try {
            BeanValidator.check(param);
            if (checkExist(param.getParentId(), param.getName(), param.getId())) {
                throw new ParamException("同一层级下存在相同名称的权限模块");
            }
            SysAclModule before = sysAclModuleMapper.selectByPrimaryKey(param.getId());
            Preconditions.checkNotNull(before, "待更新的权限模块不存在");
            SysAclModule after = SysAclModule.builder().id(param.getId()).name(param.getName())
                    .parentId(param.getParentId()).seq(param.getSeq()).status(param.getStatus())
                    .remark(param.getRemark()).level(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()))
                    .operator(RequestHolder.getCurrentUser().getUsername())
                    .operateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()))
                    .operateTime(new Date()).build();
            updateWithChild(before, after);
            sysLogService.saveAclModuleLog(before, after);
            return true;
        } catch (Exception e) {
            log.info("更新权限模块失败:{}", e);
            throw new BusinessException("更新权限模块失败！");
        }
    }

    private void updateWithChild(SysAclModule before, SysAclModule after) {
        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        if (!newLevelPrefix.equals(oldLevelPrefix)) {
            List<SysAclModule> aclModuleList = sysAclModuleMapper.selectChildAclModuleListByLevel(before.getLevel());
            if (CollectionUtils.isNotEmpty(aclModuleList)) {
                for (SysAclModule aclModule : aclModuleList) {
                    String level = aclModule.getLevel();
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        aclModule.setLevel(level);
                    }
                }
                sysAclModuleMapper.batchUpdateAclModuleList(aclModuleList);
            }
        }
        sysAclModuleMapper.updateByPrimaryKeySelective(after);
    }

    private boolean checkExist(Integer parentId, String aclModuleName, Integer aclModuleId) {
        SysAclModule module = SysAclModule.builder().parentId(parentId).name(aclModuleName).id(aclModuleId).build();
        return sysAclModuleMapper.checkExist(module) > 0;
    }

    private String getLevel(Integer aclModuleId) {
        SysAclModule sysAclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        if (sysAclModule == null) {
            return null;
        }
        return sysAclModule.getLevel();
    }

    public void delete(int aclModuleId) {
        SysAclModule aclModule = sysAclModuleMapper.selectByPrimaryKey(aclModuleId);
        Preconditions.checkNotNull(aclModule, "待删除的权限模块不存在，无法删除");
        if (sysAclModuleMapper.countAclModuleListSelective(SysAclModule.builder().parentId(aclModuleId).build()) > 0) {
            throw new ParamException("当前模块下面有子模块，无法删除");
        }
        if (sysAclMapper.countByAclModuleId(aclModuleId) > 0) {
            throw new ParamException("当前模块下面有权限点，无法删除");
        }
        sysAclModuleMapper.deleteByPrimaryKey(aclModuleId);

    }
}
